/**
 * @class Extension
 * @version 0.1.1
 * @author lisfan QQ@448182355 GIT@lisfan 
 * @createDate 17/02/2016
 * @requires jquery-1.11.3
 * @name 功能插件封装
 * @markdown
 * 
 * ## 更新
 * - 2016.3.21
 * 		- 封装通用的视图查看器
 * - 2016.4.03
 * 		- 优化SearchFilter
 * - 2016.4.04
 * 		- 优化Viewer
 * 		- 增加CascadingDroplist
 * - 2016.4.05
 * 		- 修改SearchFilter()的placeholder显示方式，避免与check()等插件功能冲突
 * - 2016.5.11
 * - 新增treeViewer *   
 *   
 *   
 *   
 *   
 *   
 */

function Extension() {
    this.fn = {
        type: "extension",
        version: "0.1.3",
        //参数接受对象形式的参数配置
        //视图查看器，单一层级
        //example:SearchFilter({trigger:触发器实例对象,viewer:视图器的选择器名称});
        //后续变动点：1.插件名称会变动，2.默认样式会变动
        Viewer: function (setting) {
            var trigger = setting.trigger;
            var viewer = setting.viewer;

            var $trigger = trigger.$me;
            var $viewer = viewer.$me;

            $trigger.attr("data-role", "trigger");
            $trigger.addClass("ext-trigger");
            $trigger.addClass("hide");
            $viewer.attr("data-role", "viewer");
            $viewer.addClass("ext-viewer");

            //包裹
            $trigger.add($viewer).wrapAll("<div class='ext-viewer ext-exter' style='position:relative;' data-role='exter'>");

            //重载配置参数
            var triggerSetting = {
                view: {
                    placeholder: $.type(trigger.config.view.placeholder) == "string" ? trigger.config.view.placeholder : "请选择",

                    enabledFilter: trigger.config.view.enabledFilter === true ? true : false, //开启列表搜索
                    //过滤类型：输入字符的类别是指定类型时才触发搜索

                    //输入类型是默认支持所有类型，纯数字=1，纯英文=2，纯中文=3，数字+英文=12，数字+中文=13，英文+中文=23，数字+英文+中文=123）
                    filterType: $.type(trigger.config.view.filterType) == "number" ? trigger.config.view.filterType : 0,
                    //过滤字段，数组类型或字符串类型，指明字段的名称，如value，或[name,value]，默认过滤节点的text()文本内容
                    filterKey: $.type(trigger.config.view.filterKey) == "string" || $.type(trigger.config.view.filterKey) == "array" ? trigger.config.view.filterKey : undefined,
                    //匹配模式：模糊匹配true，精确匹配false(默认)
                    matchMode: $.type(trigger.config.view.matchMode) == "boolean" ? trigger.config.view.matchMode : false,

                    //根据插件的勾选模式，来决定是否更新配置（需要更新节点）
                    updateConfig: trigger.config.view.enabledCheckMode === true ? false : true,
                    //假如选中模式是启用的，同时开启了勾选模式，则自动启用选中即勾选模式
                    selectIsCheck: (trigger.config.view.selectIsCheck === true || trigger.config.view.checkIsSelect === true) || (trigger.config.view.enabledSelectMode === true && trigger.config.view.enabledCheckMode === true) ? true : false,
                    checkIsSelect: (trigger.config.view.selectIsCheck === true || trigger.config.view.checkIsSelect === true) || (trigger.config.view.enabledSelectMode === true && trigger.config.view.enabledCheckMode === true) ? true : false,

                    //只要（选中模式和勾选模式）其中一种模式开启了的多选模式，那么另一种也将会是多选模式
                    checkedMultiple: (trigger.config.view.enabledSelectMode === true && trigger.config.view.selectedMultiple === true) || (trigger.config.view.enabledCheckMode === true && trigger.config.view.checkedMultiple === true) ? true : false,
                    selectedMultiple: (trigger.config.view.enabledSelectMode === true && trigger.config.view.selectedMultiple === true) || (trigger.config.view.enabledCheckMode === true && trigger.config.view.checkedMultiple === true) ? true : false,
                    //勾选模式多选数量不存在，但选中模式多选数量存在时，以选中模式的多选数量为准
                    //选中模式多选数量不存在，但勾选模式多选数量存在时，以勾选模式的多选数量为准
                    //勾选与选中模式同时存在多选数量时，以最大值为准
                    checkedSize: (!trigger.config.view.checkedSize && trigger.config.view.selectedSize) || (trigger.config.view.checkedSize && trigger.config.view.selectedSize && trigger.config.view.selectedSize > trigger.config.view.checkedSize) ? trigger.config.view.selectedSize : trigger.config.view.checkedSize,
                    selectedSize: (!trigger.config.view.selectedSize && trigger.config.view.checkedSize) || (trigger.config.view.selectedSize && trigger.config.view.checkedSize && trigger.config.view.checkedSize > trigger.config.view.selectedSize) ? trigger.config.view.checkedSize : trigger.config.view.selectedSize
                },
                callback: {
                    configCallback: function (self) {
                        if (self.config.view.enabledFilter) {
                            self.config.view.enabledControl = true;
                        }
                    },
                    configCallback: function (self) {
                        if (self.config.view.enabledFilter) {
                            //创建搜索区格式
                            //若已经存在，则不再创建
                            if (self.$control.find(".ext-filter").length <= 0) {
                                var triggerID = $trigger.attr("id");
                                var $filter = $("<div class='ext-filter'/>");
                                var $filterVal = $('<input id="' + triggerID + 'Filter" class="form-control" type="text"  style="width:50%;margin:10px">');
                                var $filterBtn = $('<a id="' + triggerID + 'Btn" href="javascript:void(0);" class="btn btn-primary"><i class="iconfont"></i>搜索</a>');
                                $filter.append($filterVal).append($filterBtn);

                                self.$control.append($filter);

                                self.$control.on("click._stopPropagation", function (event) {
                                    event.stopPropagation();
                                });

                                $filter.on("click._stopPropagation", $filterVal, function (event) {
                                    event.stopPropagation();
                                });

                                //绑定事件
                                $filter.on("click._filterNode", $filterBtn, function (event) {
                                    event.stopPropagation();

                                    //清空延迟查询定时器
                                    clearTimeout(trigger._filterTimeout);

                                    var viewerVal = $.trim($filterVal.val());

                                    //数字类型查询
                                    if (trigger.config.view.filterType == 1) {
                                        var regexpString = "/^[0-9]*$/";
                                        var regexp = eval(regexpString);
                                        if (!regexp.test(viewerVal)) return;
                                    }

                                    //英文类型查询
                                    if (trigger.config.view.filterType == 2) {
                                        var regexpString = "/^[a-zA-Z]*$/";
                                        var regexp = eval(regexpString);

                                        if (!regexp.test(viewerVal)) return;
                                    }

                                    //数字+英文类型查询
                                    if (trigger.config.view.filterType == 12) {

                                        var regexpString = "/^[0-9a-zA-Z]*$/";
                                        var regexp = eval(regexpString);

                                        if (!regexp.test(viewerVal)) return;
                                    }


                                    //中文类型查询
                                    if (trigger.config.view.filterType == 3) {
                                        var regexpString = "/^[\u4e00-\u9fa5]*$/";
                                        var regexp = eval(regexpString);

                                        if (!regexp.test(viewerVal)) return;
                                    }

                                    //数字+中文类型查询
                                    if (trigger.config.view.filterType == 13) {
                                        var regexpString = "/^[0-9\u4e00-\u9fa5]*$/";
                                        var regexp = eval(regexpString);

                                        if (!regexp.test(viewerVal)) return;
                                    }

                                    //数字+中文类型查询
                                    if (trigger.config.view.filterType == 23) {
                                        var regexpString = "/^[a-zA-Z\u4e00-\u9fa5]*$/";
                                        var regexp = eval(regexpString);

                                        if (!regexp.test(viewerVal)) return;
                                    }

                                    //数字+英文+中文类型查询
                                    if (trigger.config.view.filterType == 123) {
                                        var regexpString = "/^[0-9a-zA-Z\u4e00-\u9fa5]*$/";
                                        var regexp = eval(regexpString);

                                        if (!regexp.test(viewerVal)) return;
                                    }

                                    if (trigger.config.view.filterTimeout) {
                                        trigger._filterTimeout = setTimeout(function () {
                                            trigger.filterNode($filterVal.val(), trigger.config.view.filterKey, trigger.config.view.matchMode);
                                        }, trigger.config.view.filterTimeout);
                                    } else {
                                        trigger.filterNode($filterVal.val(), trigger.config.view.filterKey, trigger.config.view.matchMode);
                                    }
                                });



                                $filter.on("focus._stopPropagation", $filterVal, function (event) {
                                    event.stopPropagation();
                                });

                                /* 输入区无内容时，清空 */
                                $filter.on("keyup._restore", $filterVal, function (event) {
                                    event.stopPropagation();
                                    if ($.trim($filterVal.val()) == "") {
                                        //为空时，触发一次查找
                                        trigger.showAllNode();
                                    }
                                });

                                $filter.on("keydown._triggerFilter", $filterVal, function (event) {
                                    if (event.which === 13) {
                                        event.stopPropagation();
                                        event.preventDefault();
                                        $filterBtn.trigger("click");
                                        return false;
                                    }

                                    /*     if (event.which === 13) {
                                             if ($.trim($filterVal.val()) == "") {

                                                 return false;

                                             }
                                         }*/

                                });

                                //初始化
                                //初始化配置
                                //如果延迟时间未指定，则根据实际数据长度是否大于指定长度进行设置
                                if (trigger.config.view.filterTimeout === undefined) {
                                    //未设置时，取多少呢
                                    if (trigger.getAllNode().length > trigger.config.view.filterLength) {
                                        //大于500条数据时，则设置延迟加载，否则不延迟
                                        trigger.config.view.filterTimeout = 250;
                                    }
                                };

                            }
                        }
                    },
                    nodeSelected: function ($node, nodeData, self) {
                        //若开启了选中即勾选模式，同时支持选中模式时，退出该回调，只执行勾选回调即可
                        if ((self.config.view.selectIsCheck || self.config.view.checkIsSelect) && self.config.view.enabledSelectMode) {
                            return;
                        }
                        self.config.action.addViewerNode($node, nodeData, self);
                    },
                    nodeCancelSelected: function ($node, nodeData, self) {
                        //若开启了选中即勾选模式，同时支持选中模式时，退出该回调，只执行勾选回调即可
                        if ((self.config.view.selectIsCheck || self.config.view.checkIsSelect) && self.config.view.enabledSelectMode) {
                            return;
                        }
                        self.config.action.removeViewerNode($node, nodeData, self);
                    },
                    nodeChecked: function ($node, nodeData, self) {
                        self.config.action.addViewerNode($node, nodeData, self);
                    },
                    nodeCancelChecked: function ($node, nodeData, self) {
                        self.config.action.removeViewerNode($node, nodeData, self);
                    }
                },
                action: {
                    addViewerNode: function ($node, nodeData, self) {
                        //判断是否存在父节点
                        //如果存在，则不增加当前节点
                        //如果不存在，则判断是否存在当前节点，如存在不增加
                        //节点选中后，若视图器里未存在当前节点ID的节点，则增加进支
                        //如已存在，则进行替换（更新）节点数据
                        var parentFlag = false;
                        var pId;
                        if (nodeData.hasParent) {
                            var pId = nodeData.pId;

                            var $parentNode = trigger.getNodeById(pId);
                            var parentData = trigger.getDataById($parentNode)[0];
                            if (parentData.checked) {
                                return;
                            }
                        }

                        //把自身的子节点均不选中
                        //如果没有父节点，则直接选中自已   

                        var $triggerChildrenNode = trigger.getChildrenNode(trigger.getNodeById(nodeData.id));
                        for (var i = 0; i < $triggerChildrenNode.length; i++) {
                            var triggerNodeDate = trigger.getDataById($triggerChildrenNode.eq(i))[0];
                            viewer.removeNode(viewer.getNodeById(triggerNodeDate.id));
                        }

                        var $getViewerNode = viewer.getNodeById(nodeData.id);

                        var cloneData = viewer.cloneData(nodeData);

                        if ($getViewerNode.length <= 0) {
                            //视图器不存在节点，则增加
                            //如果是单选模式，先清节点
                            if (!trigger.config.view.selectedMultiple || !trigger.config.view.checkedMultiple) {
                                viewer.cleanNode();
                            }

                            //增加节点
                            viewer.addNode(cloneData);

                        } else {
                            //视图器已存在这节点，则更新
                            var index = viewer.getSiblingsNode($getViewerNode, true).index($getViewerNode);
                            viewer.removeNode($getViewerNode);
                            viewer.addNode(cloneData, index);
                        }
                        //检测视图器的节点数量，呈现显示方式
                        _autoCloseTrigger();

                        /*//节点选中后，若视图器里未存在当前节点ID的节点，则增加进支
                        //如已存在，则进行替换（更新）节点数据
                        var cloneData = viewer.cloneData(nodeData);
                        var $getViewerNode = viewer.getNodeById(nodeData.id);
                        if ($getViewerNode.length <= 0) {
                            //视图器不存在节点，则增加
                            //如果是单选模式，先清节点
                            if (!trigger.config.view.selectedMultiple || !trigger.config.view.checkedMultiple) {
                                viewer.cleanNode();
                            }

                            //增加节点
                            viewer.addNode(cloneData);

                        } else {
                            //视图器已存在这节点，则更新
                            var index = viewer.getSiblingsNode($getViewerNode, true).index($getViewerNode);
                            viewer.removeNode($getViewerNode);
                            viewer.addNode(cloneData, index);
                        }
                        //检测视图器的节点数量，呈现显示方式
                        _autoCloseTrigger();*/
                    },
                    removeViewerNode: function ($node, nodeData, self) {
                        //取消选中时
                        //判断当前节点是否存在父节点
                        //如果存在，则判断该父节点下的直接子节点，让勾选状态的显示


                        var $getViewerNode = viewer.getNodeById(nodeData.id);
                        viewer.removeNode($getViewerNode);

                        if (nodeData.hasParent) {
                            var pId = nodeData.pId;

                            var $parentNode = trigger.getNodeById(pId);

                            var $triggerChildrenNode = trigger.getChildrenNode($parentNode, true);
                            for (var i = 0; i < $triggerChildrenNode.length; i++) {
                                var triggerNodeDate = trigger.getDataById($triggerChildrenNode.eq(i))[0];
                                if (triggerNodeDate.checked) {
                                    var cloneData = viewer.cloneData(triggerNodeDate);
                                    viewer.addNode(cloneData);
                                }
                            }
                        }

                        //检测视图器的节点数量，呈现显示方式
                        _autoCloseTrigger();
                        /*//取消选中时
                        var $getViewerNode = viewer.getNodeById(nodeData.id);
                        viewer.removeNode($getViewerNode);
                        //检测视图器的节点数量，呈现显示方式
                        _autoCloseTrigger();*/
                    }
                }
            }

            //合并节点选中等回调事件
            //当第一次初始化插件时，将插件的默认事件合并，并增加一个标记
            //当第二次初始化相同插件时，根据标记来判断不再将这个默认事件合并进去
            /* log(trigger)

             //原来连接上有东西
             if (!trigger._nodeSelectedFlag) {
                 log(1888888)
                 trigger._nodeSelectedFlag = true;
             } else {
                 delete triggerSetting.callback.nodeSelected;
             }
             
             if (trigger.config.callback.nodeSelected) {
                     triggerSetting.callback.nodeSelected = _mergeFunc(triggerSetting.callback.nodeSelected, trigger.config.callback.nodeSelected);

            }

             if (!trigger._nodeCancelSelectedFlag) {
                 if (trigger.config.callback.nodeCancelSelected) {
                     triggerSetting.callback.nodeCancelSelected = _mergeFunc(triggerSetting.callback.nodeCancelSelected, trigger.config.callback.nodeCancelSelected);
                     trigger._nodeCancelSelectedFlag = true;

                 }
             } else {
                 delete triggerSetting.callback.nodeCancelSelected;
             }

             if (!trigger._nodeCheckedFlag) {
                 if (trigger.config.callback.nodeChecked) {
                     triggerSetting.callback.nodeChecked = _mergeFunc(triggerSetting.callback.nodeChecked, trigger.config.callback.nodeChecked);
                     trigger._nodeCheckedFlag = true;

                 }
             } else {
                 delete triggerSetting.callback.nodeChecked;
             }

             if (!trigger._nodeCancelCheckedFlag) {
                 if (trigger.config.callback.nodeCancelChecked) {
                     triggerSetting.callback.nodeCancelChecked = _mergeFunc(triggerSetting.callback.nodeCancelChecked, trigger.config.callback.nodeCancelChecked);
                     trigger._nodeCancelCheckedFlag = true;

                 }
             } else {
                 delete triggerSetting.callback.nodeCancelChecked;
             }*/

            //重载
            trigger.load(triggerSetting);

            //重载面板配置
            var viewerSetting = {
                view: {
                    //当2个插件都设置为可用时，才可用
                    enabled: trigger.config.view.enabled,
                    //不重载数据
                    updateConfig: true,
                    selectedMultiple: trigger.config.view.selectedMultiple,
                    selectedSize: trigger.config.view.selectedSize,
                    checkedMultiple: trigger.config.view.checkedMultiple,
                    checkedSize: trigger.config.view.checkedSize,
                    disabledMultiple: trigger.config.view.disabledMultiple,
                    disabledSize: trigger.config.view.disabledSize,
                    //单选模式不开启移除按钮
                    showRemoveIcon: trigger.config.view.selectedMultiple === true ? true : false
                },
                callback: {
                    removeIconCallback: function ($node, self) {
                        viewer.config.action.removeTriggerNode($node);
                    }
                },
                action: {
                    //视图器移除按钮事件
                    removeTriggerNode: function ($node) {
                        var nodeData = viewer.getDataById($node)[0];
                        var $triggerNode = trigger.getNodeById(nodeData.id);
                        $triggerNode.trigger("click");
                        _autoCloseTrigger();
                    }
                }
            };

            viewer.load(viewerSetting);

            trigger.ready(function () {
                //绑定视图面板点击弹出事件
                //插件启用时绑定事件，禁用时不绑定事件，且对已绑定事件移除
                if (trigger.config.view.enabled === true) {
                    $viewer.off("click._openTrigger");
                    $viewer.on("click._openTrigger", function (event) {
                        event.stopPropagation();
                        //当前弹出窗是否已显示
                        var visibleFlag = $trigger.is(":visible");
                        $(document).trigger("click._closeTrigger");
                        if (visibleFlag) {
                            //弹出窗若显示，则关闭
                            $viewer.removeClass("active");
                            $trigger.hide();
                        } else {
                            //未显示，则展开
                            $viewer.addClass("active");
                            $trigger.show();
                            //调整样式
                            $trigger.css({
                                "position": "absolute",
                                "width": $viewer.innerWidth() + "px",
                                "left": 0,
                                "zIndex": 1024
                            });
                        }
                        if ($.type(trigger.config.callback.openTrigger) == "function") {

                            trigger.config.callback.openTrigger(trigger, viewer);
                        }
                    });
                    $trigger.on("click.stopPropagation", function (event) {
                        event.stopPropagation();
                    });


                    //绑定在全局window上当前打开的下拉框事件
                    //点击空白区域关闭弹窗事件
                    $(document).off("keydown._triggerKeybord");
                    $(document).on("keydown._triggerKeybord", function (event) {
                        var $allNode = trigger.getAllNode();
                        var $keybordNode = trigger.getNodeByState($allNode, "hover");
                        var index = $allNode.index($keybordNode);

                        var $currentNode = $keybordNode;
                        if (event.which === 40 || event.which === 38) {
                            event.preventDefault();
                            $viewer.trigger("blur");
                        }

                        //向下
                        if (event.which === 40) {
                            /* 向下选择时，当列表中没有选项选中，或者处于最末条时，重置为第一项 */
                            trigger.removeNodeState($keybordNode, "hover");

                            if ($keybordNode.length <= 0 || index === $allNode.length - 1) {
                                $currentNode = trigger.getNodeByIndex(0);
                            } else {
                                $currentNode = trigger.getNodeByIndex(index + 1);
                            }
                            trigger.addNodeState($currentNode, "hover")
                        }

                        //向上
                        if (event.which === 38) {
                            /* 向上选择时，当列表中没有选项选中，或者已经处于第一条时，重置为最末项 */
                            trigger.removeNodeState($keybordNode, "hover");

                            if ($keybordNode.length <= 0 || index === 0) {
                                $currentNode = trigger.getNodeByIndex($allNode.length - 1);
                            } else {
                                $currentNode = trigger.getNodeByIndex(index - 1);
                            }
                            trigger.addNodeState($currentNode, "hover")
                        }

                        //回车
                        if (event.which === 13) {
                            $keybordNode.trigger("click");
                            return;
                        }

                        if ($keybordNode.length > 0) {
                            var currentNodeTop = $currentNode.position().top;
                            var currentNodeOuterHeight = $currentNode.outerHeight();
                            var triggerInnerHeight = $trigger.innerHeight();
                            var triggerScrollTop = $trigger.scrollTop();

                            var currentNodeTopSum = triggerScrollTop + currentNodeTop + currentNodeOuterHeight;
                            //选项达到边界时，内置滚动条滚动
                            if (triggerInnerHeight <= currentNodeTopSum) {
                                $trigger.scrollTop(currentNodeTopSum - triggerInnerHeight);
                            } else {
                                $trigger.scrollTop(0);
                            }
                        }
                    });
                } else {
                    //禁用时，移除事件
                    $viewer.off("click._openTrigger");
                    $(document).off("keydown._triggerKeybord");
                    $trigger.removeData("_callback");
                }

                //触发器关闭时触发绑定的回调事件
                $trigger.data("_callback", {});
                var triggerCallback = $trigger.data("_callback");
                triggerCallback.closeTrigger = function () {
                    if ($.type(trigger.config.callback.closeTrigger) == "function") {
                        trigger.config.callback.closeTrigger(trigger, viewer);
                    }
                }

                //初始化
                //初始化视图器的提示占位符
                if ($viewer.find(".placeholder").length <= 0) {
                    //已存在时则不再创建
                    $viewer.prepend('<div class="placeholder">' + trigger.config.view.placeholder + '</div><i class="switch-icon"></i>');
                }

                //初始化多选模式
                if (!viewer.config.view.selectedMultiple) {
                    //单选模式时，增加single样式
                    viewer.$content.addClass("single");
                } else {
                    viewer.$content.removeClass("single");
                }

                //假如视图器初始化无内容，并且触发器里存在已选中节点或已勾选节点，则初始化显示下拉列表中已选中的数据
                var $addNode = trigger.getSelectedNode();
                $addNode = $addNode.add(trigger.getCheckedNode());
                if ($addNode.length > 0) {
                    //触发器不存在已选中项
                    //显示提示占位符
                    $viewer.find(".placeholder").hide();
                    viewer.$content.show();

                    //触发器存在已选中项
                    for (var i = 0; i < $addNode.length; i++) {
                        var $currentNode = $addNode.eq(i);
                        var currentData = trigger.getDataById($currentNode)[0];
                        trigger.config.action.addViewerNode($currentNode, currentData, trigger);
                    }
                } else {
                    //触发器不存在已选中项
                    //显示提示占位符
                    $viewer.find(".placeholder").show();
                    viewer.$content.hide();
                }
            });

            //自动关闭触发器
            //检测视图器的节点数量，呈现显示方式
            function _autoCloseTrigger() {
                //检测视图器是否存在节点
                if (viewer.getAllNode().length <= 0) {
                    //不存在节点时，不主动关闭弹窗
                    $viewer.find(".placeholder").show();
                    viewer.$content.hide();
                } else {
                    $viewer.find(".placeholder").hide();
                    viewer.$content.show();
                    //满足条件后，主动关闭弹窗
                    //单选模式，选中后
                    if (!trigger.config.view.selectedMultiple) {
                        $(document).trigger("click._closeTrigger");
                    } else {
                        //多选模式时只有达到了条件才隐藏弹出框
                        if (trigger.config.view.selectedSize && (trigger.config.view.selectedSize <= viewer.getAllNode().length)) {
                            $(document).trigger("click._closeTrigger");
                        }
                    }
                }
            }
            return {
                type: "ext.viewer",
                version: "0.1",
                setting: setting,
                trigger: trigger,
                viewer: viewer
            }
        },


        //检索过滤器
        //example:SearchFilter({trigger:触发器实例对象,viewer:视图器的选择器名称});
        //后续变动点：1.插件名称会变动，2.默认样式会变动
        SearchFilter: function (setting) {
            var trigger = setting.trigger;
            var viewer = setting.viewer;

            var $trigger = trigger.$me;
            var $viewer = $(viewer).eq(0);

            $trigger.attr("data-role", "trigger");
            $trigger.addClass("ext-trigger");

            //包裹
            $trigger.add($viewer).wrapAll("<div class='ext-search-filter ext-exter' style='position:relative;' data-role='exter'>");
            $viewer.wrap("<div>");
            $viewer.parent().attr("data-role", "viewer");
            $viewer.parent().addClass("ext-viewer");
            //重载配置参数
            var triggerSetting = {
                view: {
                    //(未实现)精确存在模式，默认关闭false，不建议开启，数据量少时可开启，视图器中存在的值必须是节点text()内容必须存在的（每次点击节点时触发，关闭弹窗时触发，增加1个分割符号时触发）
                    // mustNodeMode: true,
                    //分割符符号，默认为英文逗号
                    splitSymbol: $.type(trigger.config.view.splitSymbol) == "string" ? trigger.config.view.splitSymbol : ",",
                    //提示信息占位符
                    placeholder: $.type(trigger.config.view.placeholder) == "string" ? trigger.config.view.placeholder : "--请选择--",

                    //过滤类型：输入字符的类别是指定类型时才触发搜索
                    //输入类型是默认支持所有类型，纯数字=1，纯英文=2，纯中文=3，数字+英文=12，数字+中文=13，英文+中文=23，数字+英文+中文=123）
                    filterType: $.type(trigger.config.view.filterType) == "number" ? trigger.config.view.filterType : 0,
                    //过滤字段，数组类型或字符串类型，指明字段的名称，如value，或[name,value]，默认过滤节点的text()文本内容
                    filterKey: $.type(trigger.config.view.filterKey) == "string" || $.type(trigger.config.view.filterKey) == "array" ? trigger.config.view.filterKey : undefined,
                    //匹配模式：模糊匹配true，精确匹配false(默认)
                    matchMode: $.type(trigger.config.view.matchMode) == "boolean" ? trigger.config.view.matchMode : false,

                    //当数据数量级超过指定条数时（默认超过500条）时，不实时搜索，延迟250毫秒//TODO 再次测试
                    filterLength: $.type(trigger.config.view.filterLength) == "number" ? trigger.config.view.filterLength : 500,
                    filterTimeout: $.type(trigger.config.view.filterTimeout) == "number" ? trigger.config.view.filterTimeout : undefined,

                    updateConfig: trigger.config.view.enabledCheckMode === true ? false : true,
                    //假如选中模式是启用的，同时开启了勾选模式，则启用选中即勾选模式
                    selectIsCheck: (trigger.config.view.selectIsCheck === true || trigger.config.view.checkIsSelect === true) || (trigger.config.view.enabledSelectMode === true && trigger.config.view.enabledCheckMode === true) ? true : false,
                    checkIsSelect: (trigger.config.view.selectIsCheck === true || trigger.config.view.checkIsSelect === true) || (trigger.config.view.enabledSelectMode === true && trigger.config.view.enabledCheckMode === true) ? true : false,

                    //只要开启了对应的模式，且是多选模式时就为true
                    checkedMultiple: (trigger.config.view.enabledSelectMode === true && trigger.config.view.selectedMultiple === true) || (trigger.config.view.enabledCheckMode === true && trigger.config.view.checkedMultiple === true) ? true : false,
                    selectedMultiple: (trigger.config.view.enabledSelectMode === true && trigger.config.view.selectedMultiple === true) || (trigger.config.view.enabledCheckMode === true && trigger.config.view.checkedMultiple === true) ? true : false
                },
                callback: {
                    nodeSelected: function ($node, nodeData, self) {
                        //若开启了选中即勾选模式，同时支持选中模式时，退出该回调，只执行勾选回调即可
                        if ((self.config.view.selectIsCheck || self.config.view.checkIsSelect) && self.config.view.enabledSelectMode) {
                            return;
                        }
                        self.config.action.addViewerText($node, nodeData, self);
                    },
                    nodeCancelSelected: function ($node, nodeData, self) {
                        //若开启了选中即勾选模式，同时支持选中模式时，退出该回调，只执行勾选回调即可
                        if ((self.config.view.selectIsCheck || self.config.view.checkIsSelect) && self.config.view.enabledSelectMode) {
                            return;
                        }
                        self.config.action.removeViewerText($node, nodeData, self);
                    },
                    nodeChecked: function ($node, nodeData, self) {
                        self.config.action.addViewerText($node, nodeData, self);
                    },
                    nodeCancelChecked: function ($node, nodeData, self) {
                        self.config.action.removeViewerText($node, nodeData, self);
                    }
                },
                action: {
                    addViewerText: function ($node, nodeData, self) {
                        if (trigger.config.view.selectedMultiple === true) {
                            //视图器已有内容
                            var viewerVal = $.trim($viewer.val());
                            var nodeText = $.trim($node.text());
                            //多选模式
                            //即时搜索下拉不同于EXT.Viewer扩展，视图器里的内容文本并不是节点的nodeData.name而是$node.text()
                            if (viewerVal.length === 0) {
                                //视图器无内容
                                $viewer.val(nodeText);
                            } else {
                                //取得视图器里分割的最末的位置的值，判断他是否与当前选中节点的文本值部分匹配，若有匹配到则表示正在输入的值是用于搜索的，点击选中时，将这个值移除
                                var valArray = viewerVal.split(trigger.config.view.splitSymbol);
                                if (nodeText.search(eval("/" + valArray[valArray.length - 1] + "/")) >= 0) {
                                    //部分匹配中,移除最末的值
                                    valArray.pop();
                                    //移除末尾数据后还存在值的话，
                                    if (valArray.length > 0) {
                                        $viewer.val(valArray.join(trigger.config.view.splitSymbol) + trigger.config.view.splitSymbol + nodeText);
                                    } else {
                                        $viewer.val(nodeText);
                                    }
                                } else {
                                    //未匹配中时，直接添加至末尾
                                    $viewer.val(viewerVal + trigger.config.view.splitSymbol + nodeText);
                                }
                            }
                        } else {
                            //单选
                            $viewer.val($.trim($node.text()));
                        }
                        $viewer.siblings(".placeholder").hide();
                    },
                    removeViewerText: function ($node, nodeData, self) {
                        var viewerVal = $.trim($viewer.val());
                        var nodeText = $.trim($node.text());

                        var valArray = viewerVal.split(trigger.config.view.splitSymbol);
                        valArray = $.map(valArray, function (value) {
                            //找到相同项，删除
                            if (value != nodeText) {
                                return value
                            }
                        });
                        $viewer.val(valArray.join(trigger.config.view.splitSymbol));
                        /*setTimeout(function () {
                            if ($viewer.val().length == 0) {
                                $viewer.siblings(".placeholder").show();
                            }
                        }, 0)*/
                    }
                }
            }

            //重载
            trigger.load(triggerSetting);

            //重载完成
            trigger.ready(function () {
                //全局变量：视图器上一次的值
                var _viewerVal;

                //绑定事件
                //插件启用时绑定事件，禁用时不绑定事件，且对已绑定事件移除
                if (trigger.config.view.enabled === true) {
                    //视图器获得焦点事件：弹出触发器
                    $viewer.off("focus._openTrigger");
                    $viewer.on("focus._openTrigger", function (event) {
                        event.stopPropagation();

                        //收起其他触发器和其他视图器焦点状态
                        $(document).trigger("click._closeTrigger");

                        //未显示，则展开
                        //每次获得焦点后，都重新显示出全部节点
                        trigger.showAllNode();
                        $viewer.parent().addClass("active");
                        $trigger.show();
                        //调整样式
                        $trigger.css({
                            "position": "absolute",
                            "width": $viewer.innerWidth() + "px",
                            "left": 0,
                            "top": $viewer.outerHeight() + "px", //修正IE问题
                            "zIndex": 1024
                        });

                        //绑定在全局window上当前打开的下拉框事件
                        //点击空白区域关闭弹窗事件
                        $(document).off("keydown._triggerKeybord");
                        $(document).on("keydown._triggerKeybord", function (event) {

                            var $allNode = trigger.getAllNode();
                            var $keybordNode = trigger.getNodeByState($allNode, "hover");
                            var index = $allNode.index($keybordNode);

                            var $currentNode = $keybordNode;

                            if (event.which === 40 || event.which === 38) {
                                event.preventDefault();
                                $viewer.trigger("blur");
                            }

                            //向下
                            if (event.which === 40) {
                                /* 向下选择时，当列表中没有选项选中，或者处于最末条时，重置为第一项 */
                                trigger.removeNodeState($keybordNode, "hover");

                                if ($keybordNode.length <= 0 || index === $allNode.length - 1) {
                                    $currentNode = trigger.getNodeByIndex(0);
                                } else {
                                    $currentNode = trigger.getNodeByIndex(index + 1);
                                }
                                trigger.addNodeState($currentNode, "hover")
                            }

                            //向上
                            if (event.which === 38) {
                                /* 向上选择时，当列表中没有选项选中，或者已经处于第一条时，重置为最末项 */
                                trigger.removeNodeState($keybordNode, "hover");

                                if ($keybordNode.length <= 0 || index === 0) {
                                    $currentNode = trigger.getNodeByIndex($allNode.length - 1);
                                } else {
                                    $currentNode = trigger.getNodeByIndex(index - 1);
                                }
                                trigger.addNodeState($currentNode, "hover")
                            }

                            //回车
                            if (event.which === 13) {
                                $keybordNode.trigger("click");
                                return;
                            }

                            if ($keybordNode.length > 0) {
                                var currentNodeTop = $currentNode.position().top;
                                var currentNodeOuterHeight = $currentNode.outerHeight();
                                var triggerInnerHeight = $trigger.innerHeight();
                                var triggerScrollTop = $trigger.scrollTop();

                                var currentNodeTopSum = triggerScrollTop + currentNodeTop + currentNodeOuterHeight;
                                //选项达到边界时，内置滚动条滚动
                                if (triggerInnerHeight <= currentNodeTopSum) {
                                    $trigger.scrollTop(currentNodeTopSum - triggerInnerHeight);
                                } else {
                                    $trigger.scrollTop(0);
                                }
                            }
                        });

                        var viewerVal = $.trim($viewer.val());
                        $viewer.data("lastValue", viewerVal);;
                        $viewer.data("isValueChanged", false);

                        if ($.type(trigger.config.callback.openTrigger) == "function") {
                            //检测内容是否发生变更
                            //取得当前输入框内容，暂存起来，以备关闭时检查
                            trigger.config.callback.openTrigger(trigger, $viewer);
                        }
                    });

                    //键盘按下事件：单选模式下不允许再输入分割符
                    $viewer.off("keydown._stopInputSplitSymbol");
                    $viewer.on("keydown._stopInputSplitSymbol", function (event) {
                        //暂存当前的视图器内容
                        _viewerVal = $.trim($viewer.val());

                        setTimeout(function () {
                            //输入后的文本 
                            var viewerVal = $.trim($viewer.val());

                            if (trigger.config.view.selectedMultiple) {
                                //多选模式：输入的字符不能有连续的2个分割符
                                if (viewerVal.indexOf(trigger.config.view.splitSymbol + trigger.config.view.splitSymbol) >= 0) {
                                    $viewer.val(viewerVal.replace(trigger.config.view.splitSymbol + trigger.config.view.splitSymbol, trigger.config.view.splitSymbol));
                                }
                            } else {
                                //单选模式：输入的最后一字符与分割符相同，则不准输入
                                //过滤掉所有与分割符相同的值

                                //在新值当中查找到分割符时，触发替换
                                if (viewerVal.indexOf(trigger.config.view.splitSymbol) >= 0) {
                                    $viewer.val(viewerVal.replace(trigger.config.view.splitSymbol, ""));
                                }
                            }
                        }, 0);
                    });

                    //绑定键盘keyup事件：实时搜索节点
                    //只过滤视图区最后一个内容（最后的分隔符逗号之后的内容
                    $viewer.off("keyup._filterNode");
                    $viewer.on("keyup._filterNode", function (event) {

                        //清空延迟查询定时器
                        clearTimeout(trigger._filterTimeout);

                        var viewerVal = $.trim($viewer.val());

                        //视图器内容未变化时，不执行查询
                        if (viewerVal === _viewerVal) return;

                        //数字类型查询
                        if (trigger.config.view.filterType == 1) {
                            var regexpString = "/^[0-9" + trigger.config.view.splitSymbol + "]*$/";
                            var regexp = eval(regexpString);
                            if (!regexp.test(viewerVal)) return;
                        }

                        //英文类型查询
                        if (trigger.config.view.filterType == 2) {
                            var regexpString = "/^[a-zA-Z" + trigger.config.view.splitSymbol + "]*$/";
                            var regexp = eval(regexpString);

                            if (!regexp.test(viewerVal)) return;
                        }

                        //数字+英文类型查询
                        if (trigger.config.view.filterType == 12) {
                            var regexpString = "/^[0-9a-zA-Z" + trigger.config.view.splitSymbol + "]*$/";
                            var regexp = eval(regexpString);

                            if (!regexp.test(viewerVal)) return;
                        }


                        //中文类型查询
                        if (trigger.config.view.filterType == 3) {
                            var regexpString = "/^[\u4e00-\u9fa5" + trigger.config.view.splitSymbol + "]*$/";
                            var regexp = eval(regexpString);

                            if (!regexp.test(viewerVal)) return;
                        }

                        //数字+中文类型查询
                        if (trigger.config.view.filterType == 13) {
                            var regexpString = "/^[0-9\u4e00-\u9fa5" + trigger.config.view.splitSymbol + "]*$/";
                            var regexp = eval(regexpString);

                            if (!regexp.test(viewerVal)) return;
                        }

                        //数字+中文类型查询
                        if (trigger.config.view.filterType == 23) {
                            var regexpString = "/^[a-zA-Z\u4e00-\u9fa5" + trigger.config.view.splitSymbol + "]*$/";
                            var regexp = eval(regexpString);

                            if (!regexp.test(viewerVal)) return;
                        }

                        //数字+英文+中文类型查询
                        if (trigger.config.view.filterType == 123) {
                            var regexpString = "/^[0-9a-zA-Z\u4e00-\u9fa5" + trigger.config.view.splitSymbol + "]*$/";
                            var regexp = eval(regexpString);

                            if (!regexp.test(viewerVal)) return;
                        }

                        //存在搜索内容时


                        //检索视图器的内容，查找与触发器中节点的文本内容，相等时，则显示，不相等时则消失
                        var valArray = viewerVal.split(trigger.config.view.splitSymbol);

                        //先过滤得到最后一个内容，后续查找只针对于最后一个内容
                        //初始化选中不延迟执行，后续的延迟执行
                        if (trigger.config.view.filterTimeout) {
                            trigger._filterTimeout = setTimeout(function () {
                                var $filterNode = trigger.filterNode(valArray[valArray.length - 1], trigger.config.view.filterKey, trigger.config.view.matchMode);
                            }, trigger.config.view.filterTimeout);
                        } else {
                            var $filterNode = trigger.filterNode(valArray[valArray.length - 1], trigger.config.view.filterKey, trigger.config.view.matchMode);
                        }

                        //提升性能：优先为其进行判断增加了哪些内容和删除了哪些内容
                        //从暂存中得到
                        var _valArray = _viewerVal.split(trigger.config.view.splitSymbol);

                        //过滤到得移除的项
                        //过滤到得新增的项
                        var addValArray = $.map(valArray, function (value) {
                            if ($.inArray(value, _valArray) >= 0) {
                                return null
                            } else {
                                return value;
                            };
                        });

                        var removeValArray = $.map(_valArray, function (value) {
                            if ($.inArray(value, valArray) >= 0) {
                                return null
                            } else {
                                return value;
                            };
                        });


                        var $allNode = trigger.getAllNode();

                        for (var i = 0; i < addValArray.length; i++) {
                            //只检查最后一项？
                            //逐一过滤触发器是否已存在该内容
                            for (var j = 0; j < $allNode.length; j++) {
                                var $currentNode = $allNode.eq(j);
                                var textData = $.trim($currentNode.text());
                                if (textData == $.trim(addValArray[i])) {
                                    //内容相等则选中
                                    trigger.selectNode($currentNode);
                                    //直接退出本次循环，查找下一个
                                    break;
                                }
                            }
                        }

                        for (var i = 0; i < removeValArray.length; i++) {
                            //只检查最后一项？
                            //逐一过滤触发器是否已存在该内容
                            for (var j = 0; j < $allNode.length; j++) {
                                var $currentNode = $allNode.eq(j);
                                var textData = $.trim($currentNode.text());
                                if (textData == $.trim(removeValArray[i])) {
                                    //内容相等则选中
                                    trigger.cancelSelectedNode($currentNode);
                                    //直接退出本次循环，查找下一个
                                    break;
                                }
                            }
                        }






                        /*			//筛选完毕后，如果触发器中所有节点是选中状态的则显示所有节点
                        			//他可能不是一个筛选操作
                        			var $showedNode = trigger.getShowedNode();

                        			var showFlag = true;
                        			for (var i = 0; i < $showedNode.length; i++) {
                        				var $currentNode = $showedNode.eq(i);
                        				if (!$currentNode.is(".selected")) {
                        					showFlag = false;
                        					break;
                        				}
                        			}

                        			if (showFlag === true) {
                        				trigger.showAllNode();
                        			}*/
                        /*
                        var $allNode = trigger.getAllNode();

                        //全部取消选中状态
                        trigger.cancelSelectedAllNode();

                        for (var i = 0; i < valArray.length; i++) {
                            //只检查最后一项？
                            //逐一过滤触发器是否已存在该内容
                            for (var j = 0; j < $allNode.length; j++) {
                                var $currentNode = $allNode.eq(j);
                                var textData = $.trim($currentNode.text());
                                if (textData == $.trim(valArray[i])) {
                                    //内容相等则选中
                                    trigger.selectNode($currentNode);
                                    //直接退出本次循环，查找下一个
                                    break;
                                }
                            }
                        }*/
                        if (viewerVal.length == 0) {
                            //搜索区无内容时显示所有节点
                            trigger.showAllNode();
                            /*//取消所有节点的选中状态
                            trigger.cancelSelectedAllNode();*/
                        }
                    });

                    //视图器点击事件：阻止冒泡至document关闭触发器
                    $viewer.off("click._stopPropagation");
                    $viewer.on("click._stopPropagation", function (event) {
                        event.stopPropagation();
                    });

                    //鼠标移入触发器时，blurTarget标记为true，移除时标记为false，
                    $trigger.off("mouseenter._changeBlurTarget");
                    $trigger.on("mouseenter._changeBlurTarget", function () {
                        $(this).prop("blurTarget", true);
                    });

                    $trigger.off("mouseleave._changeBlurTarget");
                    $trigger.on("mouseleave._changeBlurTarget", function () {
                        $(this).prop("blurTarget", false);
                    });

                    //视图器输入区获得焦点时：移除提示占位符
                    $viewer.off("focus._removePlaceHolder");
                    $viewer.on("focus._removePlaceHolder", function () {
                        //获取焦点时，提示占位符隐藏
                        $viewer.siblings(".placeholder").hide();
                    });

                    //视图器输入器失去焦点时：设置提示占位符
                    //当视图器失去焦点时，判断blurTarget的值，如果为true，则不触发，若为false则触发失去焦点事件
                    $viewer.off("blur._addPlaceHolder");
                    $viewer.on("blur._addPlaceHolder", function () {
                        if (!$trigger.prop("blurTarget") && $.trim($viewer.val()).length == 0) {
                            $viewer.siblings(".placeholder").show();
                        }
                    });


                    //占位符点击事件
                    $viewer.parent().on("click", ".placeholder", function (event) {
                        event.stopPropagation()
                        $viewer.trigger("focus");
                    });

                    //触发器关闭时触发绑定在触发器上的回调事件
                    $trigger.data("_callback", {});
                    var triggerCallback = $trigger.data("_callback");
                    triggerCallback.closeTrigger = function (event) {
                        //默认事件
                        var viewerVal = $.trim($viewer.val());
                        var lastValue = $viewer.data("lastValue");;
                        if (viewerVal != lastValue) {
                            //不相等，变更，保存最后一次的值
                            $viewer.data("isValueChanged", true);
                            $viewer.data("lastValue", viewerVal);
                        }
                        if ($.type(trigger.config.callback.closeTrigger) == "function") {
                            trigger.config.callback.closeTrigger(trigger, $viewer);
                        }
                        //待移除
                        if ($.type(trigger.config.callback.hidePopuper) == "function") {
                            trigger.config.callback.hidePopuper(trigger, $viewer);
                        }

                        //如果触发目标是视图器则不触发
                        if (!$(event.target).is($viewer)) {
                            $viewer.trigger("blur");
                        };
                    }
                } else {
                    //禁用输入框
                    $viewer.attr("disabled", "disabled");
                    $viewer.off("focus._openTrigger");
                    $viewer.off("keydown._stopInputSplitSymbol");
                    $viewer.off("keyup._filterNode");
                    $viewer.off("click._stopPropagation");
                    $trigger.off("mouseenter._changeBlurTarget");
                    $trigger.off("mouseleave._changeBlurTarget");
                    $viewer.off("focus._removePlaceHolder");
                    $viewer.off("blur._addPlaceHolder");
                    $(document).off("keydown._triggerKeybord");
                    $trigger.removeData("_callback");
                }

                //初始化
                //初始化配置
                //如果延迟时间未指定，则根据实际数据长度是否大于指定长度进行设置
                if (trigger.config.view.filterTimeout === undefined) {
                    //未设置时，取多少呢
                    if (trigger.getAllNode().length > trigger.config.view.filterLength) {
                        //大于500条数据时，则设置延迟加载，否则不延迟
                        trigger.config.view.filterTimeout = 250;
                    }
                };

                //初始化视图器的提示占位符
                if ($viewer.siblings(".placeholder").length <= 0) {
                    //已存在时则不再创建
                    $viewer.after('<div class="placeholder">' + trigger.config.view.placeholder + '</div><i class="switch-icon"></i>');
                }



                //触发一次脚本，让触发器内容触发视图器内容
                //先根据当前视图器里的默认文本，设置触发器里的选中状态
                var viewerVal = $.trim($viewer.val());
                if (viewerVal.length > 0) {
                    var valArray = viewerVal.split(trigger.config.view.splitSymbol);

                    var $allNode = trigger.getAllNode();
                    //过滤掉空的内容，如：",,"
                    valArray = $.grep(valArray, function (value, index) {
                        if ($.trim(value).length != 0) {
                            return value;
                        }
                    });

                    //将过滤后的值设置为新值
                    $viewer.val(valArray.join(trigger.config.view.splitSymbol));

                    for (var i = 0; i < valArray.length; i++) {
                        //只检查最后一项？
                        //逐一过滤触发器是否已存在该内容
                        for (var j = 0; j < $allNode.length; j++) {
                            var $currentNode = $allNode.eq(j);
                            var textData = $.trim($currentNode.text());
                            if (textData == $.trim(valArray[i])) {
                                //内容相等则选中
                                if (!$currentNode.is(".selected")) {
                                    trigger.selectNode($currentNode);
                                }
                                //直接退出本次循环，查找下一个
                                break;
                            }
                        }
                    }
                }

                //假如视图器初始化无内容，并且触发器里存在已选中节点或已勾选节点，则初始化显示下拉列表中已选中的数据
                var $selectedNode = trigger.getSelectedNode();
                if ($selectedNode.length > 0) {
                    //触发器存在已选中项
                    for (var i = 0; i < $selectedNode.length; i++) {
                        var $currentNode = $selectedNode.eq(i);
                        var currentData = trigger.getDataById($currentNode)[0];
                        /*hack*/
                        $currentNode.trigger("click");
                        $currentNode.trigger("click");
/*
                        trigger.config.action.addViewerText($currentNode, currentData, trigger);
*/
                    }
                    $viewer.siblings(".placeholder").hide();
                } else {
                    //触发器不存在已选中项
                    //视图器已有初始内容，且是单选模式时
                    var viewerVal = $.trim($viewer.val());

                    if (viewerVal.length > 0 && !trigger.config.view.selectedMultiple) {
                        $viewer.val(viewerVal.split(trigger.config.view.splitSymbol)[0]);
                    } else {
                        $viewer.siblings(".placeholder").show();

                    }
                }

                //初始化视图器里无内容时设置提示占位符


                /*if ($.trim($viewer.val()).length <= 0) {
                    $viewer.addClass("placeholder");
                    $viewer.val(trigger.config.view.placeholder);
                    //如果存在placeholder，则以他为准
                    if ($viewer.attr("placeholder") && $viewer.attr("placeholder").length > 0) {
                        trigger.config.view.placeholder = $viewer.attr("placeholder");

                    }
                }*/


            });
            return {
                type: "ext.searchfilter",
                version: "0.1",
                setting: setting,
                trigger: trigger,
                viewer: viewer
            }
        },
        //级联下拉列表
        //example:SearchFilter({trigger:触发器实例对象,viewer:视图器的选择器名称});
        //后续变动点：1.插件名称会变动，2.默认样式会变动
        CascadingDroplist: function (setting) {
            //默认配置 
            var _defaultSetting = {
                selector: "#dddd", //插件实例化选择器名称
                trigger: [], //触发器实例对象
                viewer: [], //视图器实例对象
                length: 3, //指定级联列表数量，根据length判断trigger和viewer等的长度，如果trigger等超过length长度将扩展length长度，如果length超过trigger，则之后随机再创建列表
                type: 1, //0 默认 一直出现，1，当前对象选择完毕后出现下一级
                placeholder: ["请选择", "请选择", "请选择县市"],

                setting: [], //高级定制项，可认分别为下拉列表定制配置参数
                simpleData: true,
                //加载方式：每个列表的数据加载方式
                //方式1：加载数据到第一个列表里，选择时根据子节点数据逐一增加至下一级列表（数据项是一个多重数组）

                //（放弃）方式2：将数据项加载到每个列表里，选择当级列表后，判断当前选中项的节点id，然后在下一级列表里筛选出父id指向当前节点ID的节点（当数据量大时，首次加载节点速度慢，筛选节点时也十分耗资源影响筛选速度）
                //2.（放弃）方式3：先对加载数据进行分组，归属于1级节点的放在第一个列表，归属2级节点的放在第二个列表，以此类推，选择列表1后，在列表2里筛选，该方法确点同方式2，但首次加载的节点数据量得到优化
                //children有可能是一个异步地址

                //带children格式的数据，可以采用筛选和加载方式
                //如果children上绑定了链接地址时，则采用加载方式，如果当前是采用分组方式则将忽略该功能
                //type: 1,
                //可以通过绑定ID的方式绑定选择器位置，如果有指明length将截断选择器数组的长度


                //支持两种数据格式
                //一级数组，带pIdd的对象(转换为children方式)
                //一级数组带层级结构的children（优先使用）
                data: [
                ]
            };

            setting = $.extend(true, _defaultSetting, setting);

            //如果自定义了列表选择器名
            if (setting.selector && setting.selector.length > 0) {
                //未定义时，自动生成
                var cascadingObj = {
                    type: "ext.cascadingdroplist",
                    version: "0.1",
                    setting: setting,
                    viewer: [],
                    trigger: []
                };

                var $selector = $(setting.selector);

                //优先创建实例化列表对象
                for (var i = 0; i < setting.length; i++) {
                    var $viewer = $("<div/>");
                    $viewer.attr("id", $selector.attr("id") + "Viewer" + i);
                    $viewer.addClass("ext-select-panelview");

                    var $trigger = $("<div/>");
                    $trigger.attr("id", $selector.attr("id") + "Droplist" + i);
                    $trigger.addClass("hide");

                    $selector.append($viewer).append($trigger);

                    var viewerObj = $viewer.panelview();

                    var triggerObj = $trigger.droplist();

                    //封装UI
                    EXT.Viewer({
                        trigger: triggerObj,
                        viewer: viewerObj
                    });

                    //为各自的下拉列表等对象设置索引序号
                    viewerObj._index = i;
                    triggerObj._index = i;

                    //将实例对象保存至级联对象中，以备调用
                    cascadingObj.viewer.push(viewerObj);
                    cascadingObj.trigger.push(triggerObj);
                }

                //重配每个列表配置

                //根据级联长度生成相同数量的下拉列表
                for (var i = 0; i < setting.length; i++) {

                    //仅第一项加载数据，其他项暂不可用
                    var triggerSetting = {
                        async: {},
                        key: {},
                        store: {},
                        view: {
                            placeholder: setting.placeholder[i]
                        },
                        callback: {}
                    };
                    if (i == 0) {
                        triggerSetting.store.data = setting.data;
                        triggerSetting.view.simpleData = setting.simpleData;
                    } else {
                        // triggerSetting.view.enabled = false;
                    }

                    //最后一项不增加回调
                    if (i >= 0) {
                        triggerSetting.callback = {
                            nodeSelected: function ($node, nodeData, self) {
                                var newTriggerSetting = {
                                    view: {
                                        enabled: true
                                    }
                                };

                                //设置数据
                                if ($.type(nodeData[self.config.key.childrenKey]) == "string") {
                                    //请求地址
                                    newTriggerSetting.async = {};
                                    newTriggerSetting.async.enabled = true;
                                    newTriggerSetting.async.url = nodeData[self.config.key.childrenKey];
                                } else if ($.type(nodeData[self.config.key.childrenKey]) == "array") {
                                    newTriggerSetting.store = {};
                                    newTriggerSetting.store.data = nodeData[self.config.key.childrenKey];
                                }

                                var nextTrigger = cascadingObj.trigger[self._index + 1];
                                var nextViewer = cascadingObj.viewer[self._index + 1];
                                //重载下一级列表实例对象
                                nextTrigger.load(newTriggerSetting);

                                nextTrigger.ready(function () {

                                    //重新实例化扩展插件
                                    EXT.Viewer({
                                        trigger: nextTrigger,
                                        viewer: nextViewer
                                    })
                                });
                            },
                            nodeCancelSelected: function ($node, nodeData, self) {
                                //当前插件的节点取消选择后，要取消该插件之后的所有节点的选中状态，同时关闭他们的可选择性
                                for (var i = self._index + 1; i < setting.length; i++) {
                                    var newTriggerSetting = {
                                        view: {
                                            enabled: false
                                        }
                                    };

                                    var nextTrigger = cascadingObj.trigger[i];
                                    var nextViewer = cascadingObj.viewer[i];
                                    //重载下一级列表实例对象
                                    nextTrigger.load(newTriggerSetting);

                                    nextTrigger.ready(function () {
                                        //重新实例化扩展插件
                                        EXT.Viewer({
                                            trigger: nextTrigger,
                                            viewer: nextViewer
                                        })
                                    });

                                }

                            }
                        };
                    }


                    cascadingObj.trigger[i].load(triggerSetting);

                }

                return cascadingObj;
            }
        }
    }

    //点击空白区域关闭弹窗事件
    $(document).on("click._closeTrigger", function () {
        //移除其他视图的焦点
        $("[data-role='viewer']").removeClass("active");
        //隐藏其他弹出框（不包括自身）
        //得到当前展开的弹出窗对象
        var $trigger = $("[data-role='trigger']").filter(":visible");
        $("[data-role='trigger']").hide();

        if ($trigger.length > 0) {
            //触发绑定在他身上的回调
            $trigger.data("_callback").closeTrigger(event);
        }
    });

    return this.fn;
};

var EXT = Extension = new Extension();